package nz.ac.massey.doi_information_extractor.parser;

import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import nz.ac.massey.doi_information_extractor.data.Author;
import nz.ac.massey.doi_information_extractor.data.AuthorList;
import nz.ac.massey.doi_information_extractor.data.Publication;

public class SpringerExportPlugin implements PluginInterface {

	private String doi;
	public Publication result = new Publication();

	public SpringerExportPlugin(String inputdoi) {
		this.doi = inputdoi;
	}

	@Override
	public void getInformationFromDOI(String doi) throws PublicationNotFoundException,
			IOException {

		// Get the page with search results for the DOI.
		URL resolvedPage;
		try {
			if (doi.contains("dx.doi.org")) {
				resolvedPage = new URL(doi);
			}
			else {
				resolvedPage = new URL("http://dx.doi.org/" + doi);
			}
		} catch (MalformedURLException e) {
			throw new PublicationNotFoundException(e.getMessage());
		}

		URLConnection doiConnection = resolvedPage.openConnection();
		doiConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)");
		
		BufferedInputStream buffer = new BufferedInputStream(doiConnection.getInputStream());

		URL exportPage = new URL("http://www.springerlink.com/content/" + doiConnection.getURL().getPath().split("/")[2] + "/export-citation/");
		
		doiConnection = exportPage.openConnection();
		doiConnection.setRequestProperty("User-Agent", "Mozilla 5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) ");

		buffer = new BufferedInputStream(doiConnection.getInputStream());

		StringBuilder builder = new StringBuilder();
		int byteRead;
		while ((byteRead = buffer.read()) != -1){
			builder.append((char) byteRead);
		}
		buffer.close();
		
		String source = builder.toString(); 
		
		// Find the __VIEWSTATE variable. 
		String viewstate = "";
		Pattern pattern = Pattern.compile(
				"<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\".*\" />", Pattern.UNIX_LINES);
		Matcher matcher = pattern.matcher(source);
		if (matcher.find() == true) {
			viewstate = source.substring(matcher.start() + 64, matcher.end() - 4);
		}
		
		// Find the __EVENTVALIDATION variable. 
		String eventvalidation = "";
		pattern = Pattern.compile(
				"<input type=\"hidden\" name=\"__EVENTVALIDATION\" id=\"__EVENTVALIDATION\" value=\".*\" />", Pattern.UNIX_LINES);
		matcher = pattern.matcher(source);
		if (matcher.find() == true) {
			eventvalidation = source.substring(matcher.start() + 76, matcher.end() - 4);
		}
		
		doiConnection = exportPage.openConnection();
		doiConnection.setRequestProperty("User-Agent", "Mozilla 5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) ");
		doiConnection.setDoInput(true);
		doiConnection.setDoOutput(true);
		doiConnection.setUseCaches(false);
		String content = "__VIEWSTATE=" + URLEncoder.encode(viewstate,"UTF-8") 
						+ "&ctl00%24ctl18%24cultureList=en-us"
						+ "&ctl00%24ctl18%24SearchControl%24BasicSearchForTextBox="
						+ "&ctl00%24ctl18%24SearchControl%24BasicAuthorOrEditorTextBox="
						+ "&ctl00%24ctl18%24SearchControl%24BasicPublicationTextBox="
						+ "&ctl00%24ctl18%24SearchControl%24BasicVolumeTextBox="
						+ "&ctl00%24ctl18%24SearchControl%24BasicIssueTextBox="
						+ "&ctl00%24ctl18%24SearchControl%24BasicPageTextBox="
						+ "&ctl00%24ContentPrimary%24ctl00%24ctl00%24Export=AbstractRadioButton"
						+ "&ctl00%24ContentPrimary%24ctl00%24ctl00%24Format=TextRadioButton"
						+ "&ctl00%24ContentPrimary%24ctl00%24ctl00%24CitationManagerDropDownList=BibTex"
						+ "&ctl00%24ContentPrimary%24ctl00%24ctl00%24ExportCitationButton=Export+Citation"
						+ "&__EVENTVALIDATION=" + URLEncoder.encode(eventvalidation,"UTF-8");

		DataOutputStream printout = new DataOutputStream (doiConnection.getOutputStream());
		printout.writeBytes(content);
		printout.flush();
	    printout.close();
	    
	    buffer = new BufferedInputStream(
	    		doiConnection.getInputStream());

		builder = new StringBuilder();
		while ((byteRead = buffer.read()) != -1){
			builder.append((char) byteRead);
		}
		buffer.close();

		// Put the source together.
		source = builder.toString();
		
		String[] bits = source.split("\n");
		
		result.setAuthors(getAuthors(bits));
		
		result.setArticleTitle(bits[3].substring(12, bits[3].length() - 3));
		
		result.setPublicationTitle(bits[4].substring(14, bits[4].length() -3));
		
		result.setPublisher(bits[5].substring(16, bits[5].length() -3));
		
		result.setIssn(bits[6].substring(11, bits[6].length() -3));
		
		result.setKeywords(bits[7].substring(14, bits[7].length() -3));
		
		result.setPageNumbers(bits[8].substring(12, bits[8].length() -3));
		
		result.setVolumeNumber(bits[9].substring(13, bits[9].length() -3));
		
		result.setEdition(bits[10].substring(12, bits[9].length() - 5));
		
		//Trim the description if necessary. 
		String description = bits[13].substring(15, bits[13].length() -3);
		if (description.length() > 1012)
		{
			description = description.substring(0,1012);
		}
		
		result.setDescription(description);
	}
	
	private AuthorList getAuthors(String[] bits) {
		AuthorList authorsList = new AuthorList();
		String source = bits[1].substring(13, bits[1].length() - 3);
		String[] authorsFurtherString = source.split("and");
		if (source != "") {
			// This is a little more tricky than the other methods, as it has to
			// fill the AuthorList with Author objects.
			Author tempAuthor = new Author();
			for (int i = 0; i < authorsFurtherString.length; i++) {
				String[] authorBits = authorsFurtherString[i].split(",");
				tempAuthor.setAuthorLastName(authorBits[0].trim());
				tempAuthor.setAuthorFirstName(authorBits[1].trim());
				authorsList.add(tempAuthor);
				tempAuthor = new Author();
			}
		}
		for (int i = 0; i < authorsList.size() ; i++) {
			Author tempAuthor = authorsList.get(i);
			tempAuthor.setOrganisation(bits[2].substring(18, bits[2].length() - 3));
			authorsList.set(i, tempAuthor);
		}
		return authorsList;
	}
	
	@Override
	public Publication call() throws Exception {
		getInformationFromDOI(doi);
		return result;
	}
}
